package parsing;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.TreeMap;

import core.City;
import core.Continent;
import core.Country;

public class GeoParser {

	/* linked list of continents */
	public static LinkedList<Continent> continents;
	/*
	 * map of countries, the map contains as a key the name of the country and
	 * as a value the country object assumption there isnt 2 countries with the
	 * same name if the user adds a country that is already exsits there is an
	 * error
	 */
	public static Map<String, Country> countries;

	public static Map<String, City> cities;
	// values extracted
	public static int numOfContinent;
	public static int numOfCountries;
	public static int numOfCities;

	// public static int cityId;

	/*
	 * gets the path to the CSV file create continents and countries or cities(
	 * depends on the flag) objects and adds them to the structure if flag=1
	 * then parser countries and continents if flag=0 then parser cities
	 */
	public static int parserContinentCountryCity(String inputFile, int flag) {
		try {
			if (flag == 1) {
				continents = new LinkedList<Continent>();
				countries = new TreeMap<String, Country>();
				numOfCountries = 0;
				numOfContinent = 0;
				countries.put("Zaire", new Country("ZR", "AF", "Zaire"));
				countries.put("Western Sahara", new Country("EH", "AF",
						"Western Sahara"));
			} else {

				cities = new HashMap<String, City>();
				numOfCities = 0;

			}
			/* open CSV file */
			BufferedReader br = null;
			br = new BufferedReader(new FileReader(new File(inputFile)));
			br.readLine();
			String currLine = null;
			currLine = br.readLine();
			while (currLine != null) {
				if (flag == 1) {
					if (!currLine.equals("")) {
						addCountryandContinent(currLine);
					} else {
						currLine = br.readLine();
						continue;
					}
				} else {
					if (!currLine.equals("")) {
						addCity(currLine);
					} else {
						currLine = br.readLine();
						continue;
					}
				}
				currLine = br.readLine();
			}
			br.close();
			if (flag == 1) {
				System.out.println(numOfContinent);// DEBUG
				System.out.println(numOfCountries);// DEBUG
			} else {
				System.out.println(numOfCities);// DEBUG
			}
		} catch (Exception e) {
			e.printStackTrace();
			return 0;
		}
		return 1;
	}

	/*
	 * the function checks if the continent is already in the list (the
	 * continent already read from the file ) if no returns 0 else returns 1
	 */
	public static int continentCheck(Continent continent) {
		Iterator<Continent> iter = continents.iterator();

		while (iter.hasNext()) {
			if (iter.next().equals(continent)) {
				return 1;
			}
		}
		return 0;
	}

	/*
	 * the function adds continent to the continents list and countries to the
	 * map
	 */
	public static void addCountryandContinent(String currLine) {
		String[] lineParts;
		String continentName;
		String continentId;
		String countryId;
		String countryName;
		if (currLine == null) {
			return;
		}
		lineParts = currLine.split(",");
		if (lineParts.length < 5) {
			return;
		}
		continentId = lineParts[1];
		countryId = lineParts[3];
		continentName = lineParts[2];
		continentName = continentName.replaceAll("^\"|\"$", "");
		countryName = lineParts[4];
		countryName = countryName.replaceAll("^\"|\"$", "");
		Continent continent = new Continent(continentName, continentId);
		if (continentCheck(continent) == 0) {
			continents.add(continent);
			numOfContinent++;
		}
		Country country = new Country(countryId, continentId, countryName);
		if (!(countries.containsValue(country))) {
			countries.put(countryName, country);
			numOfCountries++;
		}
	}

	/*
	 * the function adds city to the map of the cities notice: cityName and
	 * countryId are unique we do not allow 2 cities with the same name and
	 * country_id
	 */
	public static void addCity(String currLine) {
		String[] lineParts;
		String countryId_str;
		float longtitude;
		float latitude;
		int countryId;
		String lat_str = null;
		String lon_str = null;
		String cityName;
		String key;
		lineParts = currLine.split("\t");
		// adjusting float number so it will match to sql format
		longtitude = Float.parseFloat(lineParts[3]);
		lon_str = String.format("%.4f", longtitude);
		longtitude = Float.parseFloat(lon_str);
		latitude = Float.parseFloat(lineParts[2]);
		lat_str = String.format("%.4f", latitude);
		latitude = Float.parseFloat(lat_str);
		cityName = lineParts[1];
		countryId_str = lineParts[0];
		countryId = Integer.parseInt(countryId_str);
		cityName = cityName.replaceAll("^\"|\"$", "");
		key = countryId_str + "_" + cityName;
		if (!(cities.containsKey(key))) {
			City city = new City(cityName, latitude, longtitude, countryId);
			cities.put(key, city);
			numOfCities++;
		}

	}
}
